import algorithm, lenientops, sequtils
import bigints

proc `+`*(a: SomeInteger; b: BigInt): BigInt =
  a.initBigInt + b

proc `-`*(a: SomeInteger; b: BigInt): BigInt =
  a.initBigInt - b

proc `+`*(a: BigInt; b: SomeInteger): BigInt =
  a + b.initBigInt

proc `-`*(a: BigInt; b: SomeInteger): BigInt =
  a - b.initBigInt

proc abs*(n: BigInt): BigInt =
  if n < 0:
    -n
  else:
    n

proc toFloat*(x: float): float =
  x

proc toFloat*(n: BigInt): float =
  var e = 1.0
  for limb in n.limbs:
    result += e * limb
    e *= 4294967296.0
  if Negative in n.flags:
    result = -result

proc toBase*(n, b: BigInt): seq[BigInt] =
  if n == zero:
    return @[zero]
  var n = n
  let negative = n < zero
  if negative:
    n = -n
  while n != zero:
    result.add n mod b
    n = n div b
  if negative:
    result.applyIt(-it)
  result.reverse

proc toBase*(x: float; b: BigInt): seq[float] =
  # TODO: support arbitrarily large numbers
  if x == 0.0:
    return @[0.0]
  var n = x.int32
  let f = x - n
  let b = b.limbs[0].int32
  while n != zero:
    result.add float(n mod b)
    n = n div b
  result[0] += f
  result.reverse
